package com.tduck.cloud.api.web.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.tduck.cloud.account.entity.OrgEntity;
import com.tduck.cloud.account.entity.UserEntity;
import com.tduck.cloud.account.service.OrgService;
import com.tduck.cloud.account.service.UserService;
import com.tduck.cloud.api.web.ao.RelationshipAO;
import com.tduck.cloud.common.util.QueryWrapperUtils;
import com.tduck.cloud.common.util.RedisUtil;
import com.tduck.cloud.common.util.Result;
import com.tduck.cloud.form.entity.FormUserRelationEntity;
import com.tduck.cloud.form.entity.RelationshipEntity;
import com.tduck.cloud.form.entity.UserFormDataEntity;
import com.tduck.cloud.form.entity.UserFormEntity;
import com.tduck.cloud.form.entity.enums.FormTypeEnum;
import com.tduck.cloud.form.request.RelationshipRequest;
import com.tduck.cloud.form.service.FormUserRelationService;
import com.tduck.cloud.form.service.RelationshipService;
import com.tduck.cloud.form.service.UserFormDataService;
import com.tduck.cloud.form.service.UserFormService;
import com.tduck.cloud.form.vo.Evaluator;
import com.tduck.cloud.form.vo.RelationshipVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 关系船舶控制器
 *
 * @author Guard Baby
 * @date 2023/06/14
 */
@Slf4j
@RestController
@RequestMapping("/form/relationship")
@RequiredArgsConstructor
public class RelationShipController {

    private final RelationshipService relationshipService;
    private final OrgService orgService;
    private final UserFormService userFormService;
    private final UserService userService;
    private final RelationshipAO relationshipAO;
    private final RedisUtil redisUtil;
    private final FormUserRelationService formUserRelationService;
    private static final String USER_ORG_KEY = "user:org:%s";
    private static final String XLSX_PREFIX = ".xlsx";

    /**
     * 列表
     *
     * @param page    页面
     * @param request 请求
     * @return {@code Result<Page<RelationshipEntity>>}
     */
    @GetMapping("/list")
    public Result<Page<RelationshipEntity>> list(Page page, RelationshipRequest request) {
        QueryWrapper<RelationshipEntity> simpleQuery = QueryWrapperUtils.toSimpleQuery(BeanUtil.copyProperties(request, RelationshipEntity.class));
        simpleQuery.orderByDesc("create_time");
        return Result.success(relationshipService.page(page, simpleQuery));
    }

    @GetMapping("/listDistinct")
    public Result<List<RelationshipEntity>> listDistinct(String formKey) {
        List<RelationshipEntity> list = relationshipService.query().select("distinct evaluated").eq("form_key", formKey).list();
        UserFormEntity userFormEntity = userFormService.query().eq("form_key", formKey).one();
        for (RelationshipEntity relationshipEntity : list) {
            switch (userFormEntity.getType()) {
                case ORG:
                    relationshipEntity.setEvaluatedName(orgService.getById(relationshipEntity.getEvaluated()).getName());
                    break;
                case PERSON:
                    relationshipEntity.setEvaluatedName(userService.getById(relationshipEntity.getEvaluated()).getName());
                    break;
                default:
                    relationshipEntity.setEvaluatedName(StringUtils.EMPTY);
            }
        }
        return Result.success(list);
    }

    /**
     * 插叙聚合数据结果---假分页逻辑
     *
     * @param page    页面
     * @param request 请求
     * @return {@link Result}<{@link Page}<{@link RelationshipVo}>>
     */
    @GetMapping("/listAgg")
    public Result<Page<RelationshipVo>> listAgg(Page page, RelationshipRequest request) {
//        StopWatch stopWatch = new StopWatch();
//        stopWatch.start("1");
        Page<RelationshipVo> voPage = new Page<>();
        QueryWrapper<RelationshipEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("form_key", request.getFormKey());
        if (Objects.nonNull(request.getEvaluated())) {
            queryWrapper.eq("evaluated", request.getEvaluated());
        }
        if (StrUtil.isNotBlank(request.getEvaluatedName())) {
            List<UserEntity> userEntityList = userService.query().like("name", request.getEvaluatedName()).list();
            if (CollUtil.isNotEmpty(userEntityList)) {
                queryWrapper.in("evaluated", userEntityList.stream().map(UserEntity::getId).collect(Collectors.toList()));
            }
        }
        List<RelationshipEntity> doList = relationshipService.queryAggregateData(queryWrapper);
//        stopWatch.stop();
//        log.debug(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));
//        stopWatch.start("2");
        Map<Long, List<RelationshipEntity>> groupMap = doList.stream().collect(Collectors.groupingBy(RelationshipEntity::getEvaluated));
        List<FormUserRelationEntity> formUserRelationEntities = formUserRelationService.query().eq("form_key", request.getFormKey()).list();
        Map<Long, String> userRelationMap = formUserRelationEntities.stream().collect(Collectors.toMap(FormUserRelationEntity::getId, FormUserRelationEntity::getName));
        List<RelationshipVo> relationshipVoList = new ArrayList<>();
        for (Map.Entry<Long, List<RelationshipEntity>> entry : groupMap.entrySet()) {
            RelationshipVo vo = new RelationshipVo();
            vo.setEvaluated(entry.getKey());
            vo.setEvaluatedName(entry.getValue().get(0).getEvaluatedName());
            vo.setType(entry.getValue().get(0).getType());
            vo.setFormKey(entry.getValue().get(0).getFormKey());
            List<Evaluator> evaluators = new ArrayList<>();
            for (RelationshipEntity en : entry.getValue()) {
                Evaluator evaluator = new Evaluator();
                evaluator.setId(en.getEvaluator());
                evaluator.setName(en.getEvaluatorName());
                evaluator.setUserRelationId(en.getUserRelationId());
                evaluator.setUserRelationName(userRelationMap.get(en.getUserRelationId()));
                evaluators.add(evaluator);
            }
            vo.setEvaluators(evaluators);
            relationshipVoList.add(vo);
        }
        //分页逻辑
        long pageSize = page.getSize();
        long pageNo = page.getCurrent();
        long realSize = relationshipVoList.size();
        long total = realSize / page.getSize() + (realSize % page.getSize() == 0 ? 0 : 1);
        long formIndex = pageNo * pageSize - pageSize;
        long toIndex = pageNo * pageSize;
        voPage.setTotal(total);
        voPage.setCurrent(page.getCurrent());
        voPage.setSize(page.getSize());
        List<RelationshipVo> relationshipVos = CollectionUtil.sub(relationshipVoList, (int) formIndex, (int) toIndex);
        for (RelationshipVo relationshipVo : relationshipVos) {
            List<Evaluator> evaluators = relationshipVo.getEvaluators();
            for (Evaluator evaluator : evaluators) {
                String key = String.format(USER_ORG_KEY, evaluator.getId());
                Object orgNameObj = redisUtil.get(key);
                if (Objects.nonNull(orgNameObj)) {
                    evaluator.setOrgName((String) orgNameObj);
                } else {
                    UserEntity user = userService.getById(evaluator.getId());
                    if (Objects.nonNull(user)) {
                        OrgEntity orgEntity = orgService.getById(user.getOrgId());
                        if (Objects.nonNull(orgEntity)) {
                            evaluator.setOrgName(orgEntity.getName());
                            redisUtil.set(key, orgEntity.getName(), 60 * 10);
                        }
                    }
                }
            }
        }
        voPage.setRecords(relationshipVos);
//        stopWatch.stop();
//        log.debug(stopWatch.prettyPrint(TimeUnit.MILLISECONDS));
        return Result.success(voPage);
    }

    @PostMapping("/updateRelationShip")
    public Result<Boolean> updateRelationShip(@RequestBody RelationshipVo relationshipVo) {
        Result<Boolean> result = new Result<>();
        if (Objects.isNull(relationshipVo.getType())) {
            relationshipVo.setType(0);
        }
        if (relationshipService.updateRelationShip(relationshipVo)) {
            return Result.success(true, "保存成功");
        }
        return Result.failed("保存失败");
    }

    @PostMapping("/addRelationShip")
    public Result<Boolean> addRelationShip(@RequestBody RelationshipVo relationshipVo) {
        Result<Boolean> result = new Result<>();
        if (Objects.isNull(relationshipVo.getType())) {
            relationshipVo.setType(0);
        }
        if (relationshipService.addRelationShip(relationshipVo)) {
            return Result.success(true, "保存成功");
        }
        return Result.failed("保存失败");
    }

    @DeleteMapping("/delete")
    public Result<Boolean> delete(Long evaluated) {
        if (Objects.isNull(evaluated)) {
            return Result.failed("被评价者不能为空");
        }
        QueryWrapper<RelationshipEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("evaluated", evaluated);
        return Result.success(relationshipService.remove(queryWrapper));
    }

    /**
     * 下载模板
     *
     * @param request  请求
     * @param response 响应
     */
    @GetMapping("/download/template")
    public void downloadTemplate(@RequestParam("type") String type, HttpServletRequest request, HttpServletResponse response) {
        log.debug("type:{}", type);
        String filePath = "/excel/relationship.xlsx";
        if (FormTypeEnum.PERSON.getValue().equals(Integer.valueOf(type))) {
            filePath = "/excel/360relationship.xlsx";
        }
        ClassPathResource classPathResource = new ClassPathResource(filePath);
        String userAgent = request.getHeader("User-Agent");
        String fileName = classPathResource.getName() + XLSX_PREFIX;
        try (
                BufferedInputStream bis = new BufferedInputStream(classPathResource.getStream());
                BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
        ) {
            request.setCharacterEncoding("UTF-8");
            if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                // 非IE浏览器的处理：
                fileName = new String((fileName).getBytes("UTF-8"), "ISO-8859-1");
            }
            response.reset();
            //response.reset(）后需要重新设置跨域
            //添加响应头的跨域信息--开始
            response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.addHeader("Access-Control-Allow-Headers", "Content-Type");
            response.setContentType("application/octet-stream");
            response.addHeader("content-disposition", "attachment; filename=" + fileName);
            byte[] bytes = new byte[2048];
            int len;
            while ((len = bis.read(bytes, 0, bytes.length)) != -1) {
                bos.write(bytes, 0, len);
            }
            bos.flush();
        } catch (IOException e) {
            log.error("下载模板文件失败", e);
            throw new RuntimeException("下载模板文件失败", e);
        }
    }


    @PostMapping("/importData")
    public Result<String> importData(@RequestParam("file") MultipartFile file, @RequestParam("formKey") String formKey, @RequestParam("formType") Integer formType) throws IOException {
        return Result.success(relationshipAO.importData(file.getInputStream(), formKey, formType));
    }

    @GetMapping("/exportData")
    public void exportData(String formKey, Integer type, HttpServletResponse response) {
        log.debug("formKey:{},type:{}", formKey, type);
        relationshipAO.export(formKey, type, response);
    }

}
